package Phase1Tests;
import Phase1.*;

import java.io.IOException;
import java.util.Scanner;
import java.lang.reflect.*;
import java.net.UnknownHostException;

import junit.framework.TestCase;

public class TestDriver extends TestCase
{
	private static int SLEEP = 1000;
	private static MachineID targetMachine;
	private static int PORT = 3001;
	private Server server;
	private ObjectDB db;
	private GlobalID id;

	
	protected void setUp()
	{
		this.server = new Server();
		this.server.start();
		Scanner scan = new Scanner(System.in);
		db = ObjectDB.getDatabase();
		
		while (targetMachine == null || id == null)
		{
			try 
			{
				Thread.sleep(SLEEP);
				System.out.print("\n\nEnter the HostName or IP of Target Machine: ");
				targetMachine = new MachineID(scan.nextLine());
				id = db.get(targetMachine.getHost(), PORT, 0);
				String command = "ssh rpadilla@" + targetMachine.getIP()
					+ "cd /users/guest/r/rpadilla/eclipse/cs340omega/bin/ && java cs340omega.Server";
				Runtime.getRuntime().exec(command);
			} catch (UnknownHostException e) 
			{
				e.printStackTrace();
				targetMachine = null;
			}
			catch (IOException e)
			{
				System.out.println("Invalid command.");
				e.printStackTrace();
			} 
			catch (InterruptedException e)
			{
				System.out.println("Error having current thread Sleep 3 seconds.");
				e.printStackTrace();
			}
		}
	}
	
	protected void tearDown()
	{
		this.server.done();
		try
		{
			String command = "ssh rpadilla@" + targetMachine.getIP() + "killall java";
			Runtime.getRuntime().exec(command);
			Thread.sleep(SLEEP);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	
	public void testSynchroSend() throws UnknownHostException
	{
		try
		{
			Test1Proxy obj = new Test1Proxy(id);
			assertTrue(obj.getCount() >= 0);	
		}
		catch (NullPointerException e)
		{
			System.out.println("Null Pointer Error message: " + e.getMessage());
			System.out.println("Still alive!");
		}
	}
	
	public void testaSynchroSend() throws UnknownHostException
	{
		try
		{
			Test1Proxy obj = new Test1Proxy(id);
			obj.increment();	
		}
		catch (NullPointerException e)
		{
			e.printStackTrace();
			System.out.println("Still alive!");
		}
	}
	
	public void testUserInput() throws UnknownHostException
	{
		try
		{
			Thread.sleep(SLEEP);
			Test1Proxy obj = new Test1Proxy(id);
			Scanner scan = new Scanner(System.in);
			System.out.print("Enter a string: ");
			String input = scan.nextLine();
			String result = obj.little(1, input);
			assertTrue(result.equals("hi there.  " + 1 + input));	
			System.out.println("\tThe result is:" + result + "\n\n");
			//obj.decrement();
			
		//	obj.addStuff();
		}
		catch (NullPointerException e)
		{
			e.printStackTrace();
			System.out.println("Still alive!");
		}
		catch (InterruptedException e)
		{
			System.out.println("Error having current thread Sleep 3 seconds.");
			e.printStackTrace();
		}	
	}
	
	
	
	public static void main(String[] args)
	{
		ObjectDB db = ObjectDB.getDatabase();
		try
		{
			
			Scanner scan = new Scanner(System.in);
			
			Server server = new Server();
			server.start();
			try
			{
				Thread.sleep(SLEEP);
			}
			catch (InterruptedException e)
			{
				System.out.println("Error making process wait for server to start up");
			}
	
			//ObjectDB database = new ObjectDB();
			
			//Client.sendData("localhost", this.PORT,"No: Hello World!");
			System.out.println("\n\nEnter target computer: ");
			String location = scan.nextLine();
			targetMachine = new MachineID(location);
			
			System.out.println("Waiting for your go ahead:");
			while (!scan.nextLine().equals("")) 
			{ ; };
			System.out.println("Going!!!");

			Client.sendData(location, PORT, "No: Hello World!");
			
			//GlobalID temp = new GlobalID(targetMachine.getHost(), PORT, new LocalID());
			//GlobalID temp2 = new GlobalID(targetMachine.getHost(), PORT, new LocalID());
			
			//assert !temp.equals(temp2);
			
			GlobalID newID = new GlobalID(targetMachine.getHost(), PORT, new LocalID());
			Test1Proxy obj = new Test1Proxy(newID);
			
			db.put(newID, new Test1());
			db.finalize();
			
		
			
			try
			{	
				int num1 = 4;
				int num2 = 2;
				int num3 = 3;
				String methodName = "addThingsTogether";
				Class<?>[] paramTypes = {Long.TYPE, Long.TYPE, Long.TYPE};
				Method method = obj.getClass().getMethod(methodName, paramTypes);
				Object[] params = {num1, num2, num3};
				
				Object result = testMethod(method, obj, params);
				printResult(result);
				

				methodName = "doNothing";
				paramTypes = new Class<?>[0];
				method = obj.getClass().getMethod(methodName, paramTypes);
				params = new Object[0];
				
				testMethod(method, obj, params);
								

				//printResult(obj.AddThingsTogether(1, 2, 3));
				//printResult(obj.addStuff());				
//				printResult(obj.toString());
//				printResult(obj.isTrue());
//				printResult(obj.getCount());
//				obj.increment();
//				obj.increment();
//				printResult(obj.getCount());
//				obj.decrement();
//				printResult(obj.getCount());
				printResult(obj.addThingsTogether(4, 2, 3));
				
			}
			catch (NullPointerException e)
			{
				e.printStackTrace();
				System.out.println("Still alive!");
			}
			catch (SecurityException e)
			{
				System.out.println("Still alive!");
				e.printStackTrace();
			}
			catch (NoSuchMethodException e) 
			{
				System.out.println("Still alive!");
				e.printStackTrace();
			}
			
			//Command command = new Command();
			
			//Client.sendData(location, this.PORT, command);
			
			server.done();
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		

		
	}
	
	private static Object testMethod(Method method, Object obj, Object[] params)
	{
		try 
		{
			return method.invoke(obj, params);
		}
		catch (IllegalArgumentException e) 
		{
			e.printStackTrace();
		}
		catch (IllegalAccessException e) 
		{
			e.printStackTrace();
		}
		catch (InvocationTargetException e) 
		{
			e.printStackTrace();
		}
		
		return (Object) null;
	}
	
	
	private static void printResult(Object obj)
	{
		System.out.println("|Test Driver| The result was: " + obj + "\n");
		
	}
}
